package com.apes.fico.finance.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fico.finance.model.costcollect.WaterElectricityRent;
import com.apes.fico.finance.respository.WaterElectricityRentDao;
import com.apes.fico.finance.respository.WaterElectricityRentRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName waterElectricityRentService
 * @Description
 * @Author pengyb
 * @Date 2019/3/18 15:47
 * @Version 1.0
 **/
@Service("waterElectricityRentService")
public class WaterElectricityRentService extends DomainService {

    @Autowired
    private WaterElectricityRentRepository waterElectricityRentRepository;


    /**
     * 批量创建水电租
     *
     * @param request
     * @return
     */
    public Map save(SimpleRequest request) {
        List<WaterElectricityRent> staffSalaries = JSON.parseArray(request.getJO().getString("waterElectricityRents"), WaterElectricityRent.class);
        List<WaterElectricityRent> waterElectricityRents=new ArrayList<>();
        staffSalaries.forEach(staffSalarie -> {
            if ("bluntProvision".equals(staffSalarie.getType()) || "bluntActually".equals(staffSalarie.getType()))
                throw new RuntimeException("当前选择类型不允许保存，请确认！");
            List<Map> byCompanyDept = waterElectricityRentRepository.findByCompanyDept(staffSalarie.getCompany().getId(), staffSalarie.getDept().getId(),
                    staffSalarie.getYearMonth(), staffSalarie.getType());
            byCompanyDept.forEach(v -> {
                if (Double.valueOf(v.get("rentAmt").toString()) > 0 && staffSalarie.getRentAmt() > 0 && !staffSalarie.isValid() == false)
                    throw new RuntimeException(staffSalarie.getDept().getId() + "[" + staffSalarie.getDept().getName() + "]店租本月已创建,无法重复创建，请确认！");
                if (Double.valueOf(v.get("electricityAmt").toString()) > 0 && staffSalarie.getElectricityAmt() > 0 && !staffSalarie.isValid() == false)
                    throw new RuntimeException(staffSalarie.getDept().getId() + "[" + staffSalarie.getDept().getName() + "]电费本月已创建,无法重复创建，请确认！");
                if (Double.valueOf(v.get("waterAmt").toString()) > 0 && staffSalarie.getWaterAmt() > 0 && !staffSalarie.isValid() == false)
                    throw new RuntimeException(staffSalarie.getDept().getId() + "[" + staffSalarie.getDept().getName() + "]水费本月已创建,无法重复创建，请确认！");
            });
            if ("real".equals(staffSalarie.getType())) {
                List<WaterElectricityRent> all1 = waterElectricityRentRepository.findAll(JpaDsl.toCriteriaByEq("company.id", staffSalarie.getCompany().getId(), "dept.id", staffSalarie.getDept().getId(),
                        "yearMonth", staffSalarie.getYearMonth(), "type", "accrual", "valid", 1));

                if (all1.size() == 0) throw new RuntimeException("暂无计提,无法创建实际:" + staffSalarie.getDept().getName());
            }
            staffSalarie.setCreator(request.getPersonId());
            staffSalarie.setCreateDate(new Date());
            waterElectricityRents.add(waterElectricityRentRepository.saveAndFlush(staffSalarie));
        });
        accumulation(waterElectricityRents);
        return MapUtil.mapper("waterElectricityRents", waterElectricityRents);
    }

    /**
     * 冲红
     *
     * @param request
     * @return
     */
    public Map reversal(SimpleRequest request) {
        List<WaterElectricityRent> staffSalaries = JSON.parseArray(request.getJO().getString("waterElectricityRents"), WaterElectricityRent.class);
        List<WaterElectricityRent> waterElectricityRents = new ArrayList<>();
        staffSalaries.forEach(v -> {
            if (v.getSelected() == false) return; //未勾选的数据不变更
            if (!v.isValid())
                throw new RuntimeException(v.getDept().getId() + "[" + v.getDept().getName() + "], 已冲红，请确认！");
            if ("bluntProvision".equals(v.getType()) || "bluntActually".equals(v.getType()))
                throw new RuntimeException("当前选择类型不允许冲红，请确认！");
            v.setValid(false);
            saveAndFlush(v);
            WaterElectricityRent waterElectricityRent = new WaterElectricityRent();
            try {
                waterElectricityRent.setDept(v.getDept());//部门
                waterElectricityRent.setCompany(v.getCompany());//申报公司
                waterElectricityRent.setDeptCompany(v.getDeptCompany());//所属公司
                waterElectricityRent.setYearMonth(v.getYearMonth());//年月
                waterElectricityRent.setSummary(v.getSummary());//备注
                waterElectricityRent.setType("provision".equals(v.getType()) ? "bluntProvision" : "bluntActually");//类型
                waterElectricityRent.setWaterAmt(v.getWaterAmt() * -1);//水费
                waterElectricityRent.setElectricityAmt(v.getElectricityAmt() * -1);//电费
                waterElectricityRent.setRentAmt(v.getRentAmt() * -1);//店租
                waterElectricityRent.setOtherAmt(v.getOtherAmt() * -1);//其他
                waterElectricityRent.setCreator(request.getPersonId());
                waterElectricityRent.setCreateDate(new Date());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            waterElectricityRents.add(saveAndFlush(waterElectricityRent));
        });
        accumulation(waterElectricityRents);
        return MapUtil.mapper("waterElectricityRents", waterElectricityRents, "test", true);
    }

    private WaterElectricityRent saveAndFlush(WaterElectricityRent waterElectricityRent) {
        return waterElectricityRentRepository.saveAndFlush(waterElectricityRent);
    }

    /**
     * 回写成本归集
     *
     * @param waterElectricityRent
     */
    public void accumulation(List<WaterElectricityRent> waterElectricityRent) {
        waterElectricityRent.forEach(waterElectricityRent1 -> {
            // 统计需要回写经营成本
            if (waterElectricityRent1.getWaterAmt() != 0) {//水费
                operatingCosts(waterElectricityRent1, waterElectricityRent1.getWaterAmt(), "10", "002107");
            }
            if (waterElectricityRent1.getElectricityAmt() != 0) {//电费
                operatingCosts(waterElectricityRent1, waterElectricityRent1.getElectricityAmt(), "11", "002107");
            }
            if (waterElectricityRent1.getRentAmt() != 0) {//电租
                operatingCosts(waterElectricityRent1, waterElectricityRent1.getRentAmt(), "12", "002107");
            }
            if (waterElectricityRent1.getOtherAmt() != 0) {//其他
                operatingCosts(waterElectricityRent1, waterElectricityRent1.getOtherAmt(), "13", "002107");
            }
        });
    }

    /**
     * 公共调用经营成本方法
     *
     * @param waterElectricityRent
     * @param amt
     * @param typeCost
     * @param costType
     */
    private void operatingCosts(WaterElectricityRent waterElectricityRent, double amt, String typeCost, String costType) {
        this.invoke("finance.operatingCosts.costAccumulation", MapUtil.mapper("amt", amt, "state", waterElectricityRent.getType(),
                "yearMonth", DateUtil.format(waterElectricityRent.getYearMonth(), "yyyy-MM-dd"), "dept", waterElectricityRent.getDept().getId(),
                "typeCost", typeCost, "costType", costType, "company", waterElectricityRent.getDeptCompany().getId(),
                "sourceReceipt", "水电租","sourceId",waterElectricityRent.getId(),"declareCompany",waterElectricityRent.getCompany()));
    }

    /**
     * 导入
     *
     * @param request
     * @return
     */
    public Map importLogic(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        // 数据匹配
        List maps = builderResultList(getJO.getJSONObject("importData"));
        return MapUtil.mapper("items", maps, "msg", "");
    }

    /**
     * 导入匹配
     *
     * @param importData
     * @return
     */
    private List builderResultList(JSONObject importData) {
        List resultList = new ArrayList<>();
        importData.forEach((sheetName, excelItems) -> {
            JSONArray importDataValueArray = (JSONArray) excelItems;
            importDataValueArray.forEach(excelItem -> {
                if (((JSONArray) excelItem).size() > 0 && !((JSONArray) excelItem).get(3).equals("类型") && !((JSONArray) excelItem).get(2).equals("类型")) {
                    if ("计提".equals(((JSONArray) excelItem).get(3).toString()) || "实际发生".equals(((JSONArray) excelItem).get(3).toString())) {
                        Dept byName = SpringManager.getBean(DeptRepository.class).findOne(((JSONArray) excelItem).get(1).toString());
                        if (Objects.isNull(byName))
                            throw new RuntimeException("请检查数据部门:" + ((JSONArray) excelItem).get(1).toString());
                        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne(((JSONArray) excelItem).get(8).toString());
                        if (Objects.isNull(company))
                            throw new RuntimeException("请检查数据:" + ((JSONArray) excelItem).get(8).toString());
                        resultList.add(MapUtil.mapper(
                                "dept", byName,
                                "deptCompany", byName.getCompany(),
                                "yearMonth", ((JSONArray) excelItem).get(2).toString(),
                                "type", "计提".equals(((JSONArray) excelItem).get(3).toString()) ? "provision" : "实际发生".equals((((JSONArray) excelItem).get(3).toString())) ? "actually" : "",
                                "waterAmt", ((JSONArray) excelItem).size() > 4 && ((JSONArray) excelItem).get(4) != null && Double.valueOf(((JSONArray) excelItem).get(4).toString()) > 0 ? ((JSONArray) excelItem).get(4).toString() : 0,
                                "electricityAmt", ((JSONArray) excelItem).size() > 5 && ((JSONArray) excelItem).get(5) != null && Double.valueOf(((JSONArray) excelItem).get(5).toString()) > 0 ? ((JSONArray) excelItem).get(5).toString() : 0,
                                "rentAmt", ((JSONArray) excelItem).size() > 6 && ((JSONArray) excelItem).get(6) != null && Double.valueOf(((JSONArray) excelItem).get(6).toString()) > 0 ? ((JSONArray) excelItem).get(6).toString() : 0,
                                "otherAmt", ((JSONArray) excelItem).size() > 7 && ((JSONArray) excelItem).get(7) != null && Double.valueOf(((JSONArray) excelItem).get(7).toString()) > 0 ? ((JSONArray) excelItem).get(7).toString() : 0,
                                "company", company,
                                "summary", ((JSONArray) excelItem).size() > 9 && ((JSONArray) excelItem).get(9) != null ? ((JSONArray) excelItem).get(9).toString() : null
                        ));
                    } else {
                        Dept byName = SpringManager.getBean(DeptRepository.class).findOne(((JSONArray) excelItem).get(0).toString());
                        if (Objects.isNull(byName))
                            throw new RuntimeException("请检查数据部门:" + ((JSONArray) excelItem).get(1).toString());
                        PartyRole company = SpringManager.getBean(PartyRoleRepository.class).findOne(((JSONArray) excelItem).get(7).toString());
                        if (Objects.isNull(company))
                            throw new RuntimeException("请检查数据:" + ((JSONArray) excelItem).get(7).toString());
                        resultList.add(MapUtil.mapper(
                                "dept", byName,
                                "deptCompany", byName.getCompany(),
                                "yearMonth", ((JSONArray) excelItem).get(1).toString(),
                                "type", "计提".equals(((JSONArray) excelItem).get(2).toString()) ? "provision" : "实际发生".equals((((JSONArray) excelItem).get(2).toString())) ? "actually" : "",
                                "waterAmt", ((JSONArray) excelItem).size() > 3 && ((JSONArray) excelItem).get(3) != null && Double.valueOf(((JSONArray) excelItem).get(3).toString()) > 0 ? ((JSONArray) excelItem).get(3).toString() : 0,
                                "electricityAmt", ((JSONArray) excelItem).size() > 4 && ((JSONArray) excelItem).get(4) != null && Double.valueOf(((JSONArray) excelItem).get(4).toString()) > 0 ? ((JSONArray) excelItem).get(4).toString() : 0,
                                "rentAmt", ((JSONArray) excelItem).size() > 5 && ((JSONArray) excelItem).get(5) != null && Double.valueOf(((JSONArray) excelItem).get(5).toString()) > 0 ? ((JSONArray) excelItem).get(5).toString() : 0,
                                "otherAmt", ((JSONArray) excelItem).size() > 6 && ((JSONArray) excelItem).get(6) != null && Double.valueOf(((JSONArray) excelItem).get(6).toString()) > 0 ? ((JSONArray) excelItem).get(6).toString() : 0,
                                "company", company,
                                "summary", ((JSONArray) excelItem).size() > 8 && ((JSONArray) excelItem).get(8) != null ? ((JSONArray) excelItem).get(8).toString() : null
                        ));
                    }
                }
            });
        });
        return resultList;
    }

    /**
     * 操作页面查询
     *
     * @param request
     * @return
     */
    public List findOneToList(SimpleRequest request) {
        JSONObject object = request.getJO();
        if (StringUtils.isEmpty(object.get("type"))) throw new RuntimeException("类型必选，请选择！");
        JSONArray jsonArray = SpringManager.getBean(WaterElectricityRentDao.class).queryAllTransactionFlow(object, request.getPostId());
        List result = jsonArray.stream().map(
                item -> {
                    JSONObject jsonObject = (JSONObject) item;
                    return MapUtil.mapper(
                            "id", jsonObject.getString("ID"),
                            "dept", SpringManager.getBean(DeptRepository.class).findOne(jsonObject.getString("DEPT_ID")),
                            "deptCompany", SpringManager.getBean(PartyRoleRepository.class).findOne(jsonObject.getString("DEPT_COMPANY_ID")),
                            "yearMonth", jsonObject.getString("YEAR_MONTH"),
                            "type", jsonObject.getString("TYPE"),
                            "waterAmt", jsonObject.getString("WATER_AMT"),
                            "electricityAmt", jsonObject.getString("ELECTRICITY_AMT"),
                            "rentAmt", jsonObject.getString("RENT_AMT"),
                            "otherAmt", jsonObject.getString("OTHER_AMT"),
                            "summary", jsonObject.getString("SUMMARY"),
                            "valid", jsonObject.getString("VALID"),
                            "company", SpringManager.getBean(PartyRoleRepository.class).findOne(jsonObject.getString("COMPANY_ID"))
                    );
                }
        ).collect(Collectors.toList());
        return result;
    }

    public com.apestech.framework.json.JSONObject internalHelpReturnQuery(SimpleRequest request) throws Exception {
        JSONObject jo = request.getJO();
        JSONArray condition = jo.getJSONArray("condition");
        if (condition != null) {
            for (int i = 0; i < condition.size(); i++) {
                if ("ACCRUAL_DATE".equals(condition.getJSONObject(i).getString("field"))) {
                    JSONObject json = new JSONObject();
                    if ("GTE".equals(condition.getJSONObject(i).getString("operator"))) {
                        json.put("field", "ACCRUAL_DATE_START");
                        json.put("operator", "EQ");
                        json.put("value", condition.getJSONObject(i).getString("value"));
                        json.put("type", "date");
                        condition.add(json);
                    } else if ("LTE".equals(condition.getJSONObject(i).getString("operator"))) {
                        json.put("field", "ACCRUAL_DATE_END");
                        json.put("operator", "EQ");
                        json.put("value", condition.getJSONObject(i).getString("value"));
                        json.put("type", "date");
                        condition.add(json);
                    }
                }
                if ("REAL_DATE".equals(condition.getJSONObject(i).getString("field"))) {
                    JSONObject json = new JSONObject();
                    if ("GTE".equals(condition.getJSONObject(i).getString("operator"))) {
                        json.put("field", "REAL_DATE_START");
                        json.put("operator", "EQ");
                        json.put("value", condition.getJSONObject(i).getString("value"));
                        json.put("type", "date");
                        condition.add(json);
                    } else if ("LTE".equals(condition.getJSONObject(i).getString("operator"))) {
                        json.put("field", "REAL_DATE_END");
                        json.put("operator", "EQ");
                        json.put("value", condition.getJSONObject(i).getString("value"));
                        json.put("type", "date");
                        condition.add(json);
                    }
                }
            }
            jo.put("condition", condition);
        }
        return com.apestech.framework.json.JSON.toJSON(jo.toJSONString());
    }
}
